package com.szj.coroutine.project.jvm.blog5

import com.szj.coroutine.project.bean.NetWorkBean
import com.szj.coroutine.project.jvm.util.NetWorkApi
import com.szj.coroutine.project.jvm.util.printlnCC
import com.szj.coroutine.project.jvm.util.printlnThread
import kotlinx.coroutines.*
import kotlinx.coroutines.test.setMain
import kotlin.coroutines.*
import kotlinx.coroutines.delay
import okhttp3.ResponseBody
import retrofit2.*
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.Executors
import kotlin.concurrent.thread
import kotlin.system.measureTimeMillis

/*
 * 作者: 史大拿
 * 时间: 2023/2/20$ 15:22$
 */
//
//// TODO ============== 不使用 suspendCoroutine写法 ==============
//private suspend fun requestLoginNetworkData(account: String, pwd: String) =
//    withContext(Dispatchers.IO) {
//        delay(2000)// 模拟请求数据
//        if (account == "123456789" && pwd == "666666") {
//            Result.success("登陆成功")
//        } else {
//            Result.failure(Throwable("登陆失败"))
//        }
//    }
//
//fun main() = runBlocking<Unit> {
//    val deferred = async {
//        // 模拟网络请求
//        requestLoginNetworkData("987654321", "666666")
//    }
//    // 获取网络返回数据，判断成功与失败
//    val result = deferred.await()
//
//    // result.getOrDefault("") // 如果返回错误使用 默认值
//    // result.getOrThrow() // 如果返回错误使用 错误
//    // result.getOrNull() // 如果返回错误使用 null
//    result.onSuccess {
//        printlnThread("登陆成功:${result.getOrNull()}")
//    }.onFailure {
//        printlnThread("登陆失败:${result.getOrNull()}")
//    }
//
//
//    // 方式二。。
////    if (result.isSuccess) {
////        printlnThread("登陆成功:${result.getOrNull()}")
////    } else if (result.isFailure) {
////        // result.getOrDefault("") // 如果返回错误使用 默认值
////        // result.getOrThrow() // 如果返回错误使用 错误
////        // result.getOrNull() // 如果返回错误使用 null
////        printlnThread("登陆失败:${result.getOrNull()}")
////    }
//}


// TODO ============== 使用 suspendCoroutine写法 ==============
//private suspend fun <T> requestLoginNetworkData(account: String, pwd: String): String {
//    return withContext(Dispatchers.IO) {
////        delay(2000)  // 模拟网络耗时需要2s
//        return@withContext suspendCoroutine<String> {
//            if (account == "123456789" && pwd == "666666") {
//                it.resume("登陆成功")
//            } else {
//                it.resumeWithException(RuntimeException("登陆失败"))
//            }
//        }
//    }
//}
//
//suspend fun main() = runBlocking<Unit> {
//    val scope = CoroutineScope(Dispatchers.IO)
//
//    // 开启一个协程
//    val deferred = scope.async {
//        // 模拟网络请求
//        requestLoginNetworkData<String>("987654321", "666666")
//    }
//    // 获取网络返回数据，判断成功与失败
//    val result = runCatching {
//        deferred.await()
//    }
//    result.onSuccess {
//        printlnThread("登陆成功:${result.getOrNull()}")
//    }.onFailure {
//        printlnThread("登陆失败:${result.getOrNull()}")
//    }
//}

// TODO ============== 使用 suspendCancellableCoroutine 写法 ==============
private suspend fun <T> requestLoginNetworkData2(account: String, pwd: String): String {
    delay(2000)  // 模拟网络耗时需要2s
    return suspendCancellableCoroutine {
        if (account == "123456789" && pwd == "666666") {
            it.resume("登陆成功")
        } else {
            println("执行了")
            it.resumeWithException(RuntimeException("RuntimeException登陆失败"))
        }

        // 监听是否cancel
        it.invokeOnCancellation {
            println("suspend关闭了")
        }
    }
}





suspend fun main() = runBlocking<Unit> {
    val scope = CoroutineScope(Dispatchers.IO)

    // 开启一个协程
    val deferred = scope.async {
        // 模拟网络请求
        requestLoginNetworkData2<String>("987654321", "666666")
    }
    // 获取网络返回数据，判断成功与失败
    val result = runCatching {
        deferred.await()
    }
    result.onSuccess {
        printlnThread("登陆成功:${it}")
    }.onFailure {
        printlnThread("登陆失败:${it.message}")
    }
}


// TODO ============== 使用 suspendCancellableCoroutine 实际开发场景 写法 ==============
//
//private fun createApi() = run {
//    // https://api.apiopen.top/api/getHaoKanVideo?page=0&size=2
//    Retrofit.Builder()
//        .baseUrl(NetWorkApi.BASE_URL)
//        .addConverterFactory(GsonConverterFactory.create())
//        .build()
//        .create(NetWorkApi::class.java)
//}
//
//private suspend fun requestNetWorkData() = withContext(Dispatchers.IO) {
//    val api = createApi()
//    val data = api.requestNetWorkData()
//    printlnThread("当前线程")
//    data.await()
//}
//suspend fun main() {
//    val useTime = measureTimeMillis {
//        runBlocking {
//            val result = runCatching {
//                requestNetWorkData() // 网络请求
//            }
//            result.onSuccess {// 数据返回
//                printlnThread("返回正确结果为:$it")
//            }.onFailure {
//                printlnThread("请求失败错误为:${it.message}")
//            }
//        }
//    }
//    println("使用时间:$useTime")
//}
//







